﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Xml.Linq;

namespace ExcelToOracle
{
    public class ImportTemplate
    {
        public string FileName { get; set; }
        public string DbTable { get; set; }
        public List<FieldTplt> Constants { get; set; }
        public List<FieldTplt> Fields { get; set; }

        private ImportTemplate()
        {
            Constants = new List<FieldTplt>();
            Fields = new List<FieldTplt>();
        }

        public override string ToString()
        {
            return string.Format("{0} ({1})", DbTable, FileName);
        }

        public static ImportTemplate Build(string tableName, List<FieldTplt> constants, List<FieldTplt> fields)
        {
            ImportTemplate template = new ImportTemplate();
            template.DbTable = tableName;
            template.Constants = constants;
            template.Fields = fields;
            return template;
        }

        public static ImportTemplate Load(string filePath)
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(filePath);

            ImportTemplate template = new ImportTemplate();
            template.FileName = new FileInfo(filePath).Name;
            template.DbTable = xmlDoc.DocumentElement.Attributes["db-table"].Value;

            XmlNodeList constantNodes = xmlDoc.SelectNodes(".//excel-doc/constants/field");

            XmlNodeList fieldNodes = xmlDoc.SelectNodes(".//excel-doc/fields/field");

            foreach (XmlNode node in constantNodes)
            {
                string type = string.Empty;
                try
                {
                    type = node.Attributes["type"].Value.ToLower();
                }
                catch
                {
                    type = "string";
                }
                string dbValue = string.Empty;
                try
                {
                    dbValue = node.Attributes["db"].Value;
                }
                catch
                {
                    dbValue = string.Empty;
                }
                if (!string.IsNullOrEmpty(dbValue))
                {
                    template.Constants.Add(new FieldTplt(string.Empty, dbValue, type));
                }
            }

            foreach (XmlNode node in fieldNodes)
            {
                string type = string.Empty;
                try
                {
                    type = node.Attributes["type"].Value;
                }
                catch
                {
                    type = "string";
                }
                string excelColumnName = string.Empty;
                try
                {
                    excelColumnName = node.Attributes["excel"].Value;
                }
                catch
                {
                    excelColumnName = string.Empty;
                }

                
                string dbValue = string.Empty;
                try
                {
                    dbValue = node.Attributes["db"].Value;
                }
                catch
                {
                    dbValue = string.Empty;
                }

                if (!string.IsNullOrEmpty(dbValue)&& !string.IsNullOrEmpty(excelColumnName))
                {
                    template.Fields.Add(new FieldTplt(excelColumnName, dbValue, type));
                }
            }

            return template;
        }

        public static List<ImportTemplate> LoadAll()
        {
            List<ImportTemplate> templates = new List<ImportTemplate>();

            string[] files = System.IO.Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory + "./Configs/", "*.xml");
            foreach(string file in files)
            {
                templates.Add(Load(file));
            }

            return templates;
        }

        public static bool Save(string filePath, ImportTemplate template)
        {
            XDocument xDoc = new XDocument();
            XElement xRoot = new XElement("excel-doc",
                    new XAttribute("db-table", template.DbTable));

            XElement xConst = new XElement("constants");
            foreach (FieldTplt field in template.Constants)
            {
                xConst.Add(
                    new XElement("field",
                        new XAttribute("excel", field.ExcelColumn),
                        new XAttribute("db", field.TableColumn),
                        new XAttribute("type", field.FullType)));

            }
            xRoot.Add(xConst);

            XElement xField = new XElement("fields");
            foreach (FieldTplt field in template.Fields)
            {
                xField.Add(
                    new XElement("field",
                        new XAttribute("excel", field.ExcelColumn),
                        new XAttribute("db", field.TableColumn),
                        new XAttribute("type", field.FullType)));

            } 
            xRoot.Add(xField);
            xDoc.Add(xRoot);

            try
            {
                xDoc.Save(filePath);
                return true;
            }
            catch
            {
                return false;
            }
        }

    }

    public class FieldTplt
    {
        public string ExcelColumn { get; set; }
        public string TableColumn { get; set; }
        public string Type { get; set; }
        public string TypeData { get; set; }

        public string FullType { get; private set; }

        public FieldTplt()
        {
        }

        public FieldTplt(string excelColumn, string tableColumn, string type)
        {
            ExcelColumn = excelColumn;
            TableColumn = tableColumn;
            FullType = type;
            if (!string.IsNullOrEmpty(type))
            {
                string[] typeInfos = type.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                if (typeInfos.Length > 0)
                {
                    Type = typeInfos[0];
                    if (typeInfos.Length == 2)
                    {
                        TypeData = typeInfos[1];
                    }
                }
            }
        }

    }

    public class ConstantValues
    {
        public List<ConstantValue> Values { get; set; }

        public ConstantValues()
        {
            Values = new List<ConstantValue>();
        }
    }

    public class ConstantValue
    {
        public FieldTplt Field { get; set; }
        public string Value { get; set; }
        public ConstantValue()
        {
        }

        public ConstantValue(FieldTplt field, string value)
        {
            Field = field;
            Value = value;
        }
    }
}
